package com.leyou.gateway.filters;

import com.leyou.common.auth.entity.Payload;
import com.leyou.common.auth.entity.UserInfo;
import com.leyou.common.auth.utils.JwtUtils;
import com.leyou.common.utils.CookieUtils;
import com.leyou.gateway.config.AuthProperties;
import com.leyou.gateway.config.JwtProperties;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

import java.util.List;

import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.FORM_BODY_WRAPPER_FILTER_ORDER;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE;

@Component
public class AuthFilter extends ZuulFilter {

    @Autowired
    private JwtProperties jwtProperties;

    @Autowired
    private AuthProperties authProperties;

    @Override
    public String filterType() { //过滤的类型  前置  进行中 后置 异常
        return PRE_TYPE;
    }

    @Override
    public int filterOrder() {  //过滤器的执行顺序 值越小越靠前执行
        return FORM_BODY_WRAPPER_FILTER_ORDER-1;
    }

    @Override
    public boolean shouldFilter() {  // 是否要进入到run方法中
//        判断有哪些方法要进入run方法，有哪些不用进入到run方法
        List<String> allowPaths = authProperties.getAllowPaths();
//        当前请求是allowPaths的其中一个的时候这个方法return false ,意味着不在进入到run方法中判断token了
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        String uri = request.getRequestURI();
        for (String allowPath : allowPaths) {   //uri   /api/user/check/12345/1   allowPath: /api/user/check
            if(uri.startsWith(allowPath)){
                return false;
            }
        }
        return true; //意味着继续会进入到run方法中判断token
    }

    @Override
    public Object run() throws ZuulException {   //具体业务实现的位置
//        判断token是否能被成功解密
//        第一步：获取token
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        String token = CookieUtils.getCookieValue(request, jwtProperties.getUser().getCookieName());
//        第二步：解密token
        try {
            Payload<UserInfo> payload = JwtUtils.getInfoFromToken(token, jwtProperties.getPublicKey(), UserInfo.class);
            UserInfo userInfo = payload.getUserInfo();
            Long useId = userInfo.getId();
//            把这个userId发送到微服务中
            ctx.addZuulRequestHeader("USER_ID",useId.toString());//请求微服务 带一个头信息
            String role = userInfo.getRole();
            //  normal vip  svip
            //TODO 虽然能解析到用户，其实在这里还应该根据用户的角色判断是否能进入到相关的微服务中
        } catch (Exception e) {
//            出异常意味着没有解析成功，不能进入到微服务中
            ctx.setSendZuulResponse(false);
            ctx.setResponseStatusCode(HttpStatus.FORBIDDEN.value());
            e.printStackTrace();
        }
        return null;
    }
}
